#include "FileManager.h"
#include "FileSender.h"
#include "FileReceiver.h"
#include "Define.h"
#include "mainwindow.h"

FileManager::FileManager()
{

}

FileManager::~FileManager()
{
	if (_thread != NULL)
		delete _thread;
}

bool FileManager::Initialize(int capacity)
{
	bool init = false;
	_thread = new QThread;
	if (_thread != NULL)
	{
		_capacity = capacity;
		listen(QHostAddress::Any, FILE_PORT);

		moveToThread(_thread);
		_thread->start();
		init = true;
	}
	return init;
}

void FileManager::AddSendTask(QHostAddress addr, QString filePath)
{
	_mutex.lock();
	if (_sendTask.count() < _capacity)
	{
		if (!addr.isNull())
		{
			if (!_sendTask.contains(FileKey(QFileInfo(filePath).fileName(), addr, Tx)))
			{
				FileSender *sender = new FileSender;
				if (sender != NULL)
				{
					if (sender->Initialize(addr, FILE_PORT, filePath))
					{
						_sendTask.insert(sender->GetKey(), sender);

						connect(sender, SIGNAL(sigStarted(FileKey, long long)),
								this, SLOT(OnStart(FileKey, long long)), Qt::QueuedConnection);
						connect(sender, SIGNAL(sigError(FileKey, QString)),
								this, SLOT(OnError(FileKey, QString)), Qt::QueuedConnection);
						connect(sender, SIGNAL(sigFileSent(FileKey,int)),
								this, SLOT(OnProcessing(FileKey, int)), Qt::QueuedConnection);
						connect(sender, SIGNAL(sigComplete(FileKey)), this, SLOT(OnComplete(FileKey)), Qt::QueuedConnection);
					}
					else
						qDebug() << "FileSender::Initialize() : Initialize failed.";
				}
				else
					qDebug() << "FileTransferManager::AddTask() : Not enough memory.";
			}
			else
				emit sigNotice("FileTransferManager::AddTask() : File is already transffering.");
		}
		else
			emit sigNotice("FileTransferManager::Addtask() : Addressee is not specified");
	}
	else
		emit sigNotice("FileManager::AddSendTask() : capacity constraint");
	_mutex.unlock();
}

void FileManager::incomingConnection(int socketDescriptor)
{
	_mutex.lock();
	if (_recvTask.count() < _capacity)
	{
		FileReceiver *receiver = new FileReceiver();
		if (receiver != NULL)
		{
			if (receiver->Initialize(socketDescriptor))
			{
				connect(receiver, SIGNAL(sigStarted(FileKey, long long)),
						this, SLOT(OnStart(FileKey, long long)), Qt::QueuedConnection);
				connect(receiver, SIGNAL(sigError(FileKey, QString)),
						this, SLOT(OnError(FileKey, QString)), Qt::QueuedConnection);
				connect(receiver, SIGNAL(sigFileReceived(FileKey,int)),
						this, SLOT(OnProcessing(FileKey, int)), Qt::QueuedConnection);
				connect(receiver, SIGNAL(sigComplete(FileKey)), this, SLOT(OnComplete(FileKey)), Qt::QueuedConnection);
			}
			else
				qDebug() << "FileManager::AddRecvTask() : Initialize failed";
		}
		else
			qDebug() << "FileManager::AddRecvTask() : not enough memory";
	}
	else
		emit sigNotice("FileManager::AddRecvTask() : capacity constraint");
	_mutex.unlock();
}


bool FileManager::DeleteTask(FileKey key)
{
	bool deleted = false;
	if ((key.GetMode() == Rx) && _recvTask.contains(key))
	{
		_mutex.lock();
		_recvTask.remove(key);
		_mutex.unlock();
		deleted = true;
	}
	else if (key.GetMode() == Tx && _sendTask.contains(key))
	{
		_mutex.lock();
		_sendTask.remove(key);
		_mutex.unlock();
		deleted = true;
	}
	return deleted;
}

void FileManager::OnStart(FileKey key, long long size)
{
	QString mode = "[Receive]";
	if (key.GetMode() == Tx)
		mode = "[Send]";
	else
	{
		FileReceiver *receiver = qobject_cast<FileReceiver *>(sender());
		_mutex.lock();
		_recvTask.insert(key, receiver);
		_mutex.unlock();
	}
	emit sigNotice(mode + key.GetFileName());
	emit sigMakeProgressBar(key, size);
}

void FileManager::OnError(FileKey key, QString errorStr)
{
	if (DeleteTask(key))
	{
		QString mode = "[Receive]";
		if (key.GetMode() == Tx)
			mode = "[Send]";
		emit sigNotice(errorStr + mode);
	}
	else
		qDebug() << "FileManager::OnError() : DeleteTask failed";
}

void FileManager::OnProcessing(FileKey key, int nbytes)
{
	emit sigOnProcessing(key, nbytes);
}

void FileManager::OnComplete(FileKey key)
{
	if (DeleteTask(key))
	{
		QString mode = "[Receive]";
		if (key.GetMode() == Tx)
			mode = "[Send]";
		QString fileName = key.GetFileName();
		emit sigNotice(mode + fileName + "completed.");
		emit sigEnableProgressBarButton(key);
	}
	else
		qDebug() << "FileManager::OnComplete() : DeleteTask failed";
}
